package com.example.websocket.ws;

import com.example.websocket.pojo.ws.ResultMessage;

import com.example.websocket.utils.MessageUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;


import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static com.example.websocket.constants.Constants.*;
import static com.example.websocket.constants.Constants.GROUP_KEY;

/**
 * @ author 韩
 * time: 2024/2/12 17:15
 */
@ServerEndpoint(value = "/chat",configurator = GetHttpSessionConfigurator.class)
@Slf4j
@Component
public class ChatEndPoint {
    private static ApplicationContext applicationContext;
    public static void setApplicationContext(ApplicationContext applicationContext) {
        ChatEndPoint.applicationContext = applicationContext;
    }

    // 用来存储每一个客户端对象对应的ChatEndpoint对象
    private static final Map<String,ChatEndPoint> onlineUsers = new ConcurrentHashMap<>();

    //声明session对象，通过该对象可以发送消息给指定的用户
    private Session session;
    //声明一个HttpSession对象，我们之前再HttpSession对象中存储了用户名
    private HttpSession httpSession;

    private StringRedisTemplate redisTemplate;
    private String username;
    /**
     * 建立websocket连接后，被调用
     * @param session
     *
     * 改造一下主要是实现一个群聊的功能，该开始的群聊其实是伪群聊，因为他并没有创建群聊的操作，而是直接去遍历所有的用户
     *
     *
     */



    @OnOpen
    // 连接建立时被调用
    public void onOpen(Session session, EndpointConfig config) throws IOException {
        // 1.将局部的session进行保存
        this.session = session;
        // 2.获取httpSession对象
        this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        // 3.将当前对象存储到容器中, 获取当前登录的用户
        username = (String) this.httpSession.getAttribute("username");
        System.out.println(username + "open");

        onlineUsers.put(username,this);
        // 把所有的redis里的消息遍历 发送到前端

        redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
        Set range = redisTemplate.opsForZSet().range(MESSAGE_KEY, 0, -1);

        range.forEach((v) -> {
            try {
                this.session.getBasicRemote().sendText((String) v);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }



    @OnMessage
    // 接收到客户端发送的数据时被调用
    public void onMessage(String message,Session session) {
        System.out.println(message);
        // 因为现在群聊作为一个选项存在 所以说得有多次初始化 刚进页面默认在群聊 onopen初始化了
        // 然后点击到群聊的时候直接触发方法发送一个init的key
        // 然后是一个正常发送和撤回 发送是
        boolean flag = true;
        try {
            // 发过来一个对象，也是value能解析成功就证明要撤回这个消息
            ObjectMapper objectMapper = new ObjectMapper();
            ResultMessage message1 = objectMapper.readValue(message, ResultMessage.class);
        } catch (JsonProcessingException e) {
            flag = false;
        }
        if (flag) {
            redisTemplate.opsForZSet().remove(MESSAGE_KEY, message);

            // 挨个遍历已登录用户，然后发送数据，把对应消息清除了,在前端也要遍历，需要一个key，还是以数据体为key吧
            onlineUsers.forEach((k,v) -> {
                try {
                    ObjectMapper objectMapper = new ObjectMapper();
                    ResultMessage message1 = objectMapper.readValue(message, ResultMessage.class);
                    System.out.println(message1.getTime());
                    v.session.getBasicRemote().sendText(String.valueOf(message1.getTime()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });

        } else {
            // 传过来的message就直接是一个字符串，说明要发送消息
            // 获取推送给指定用户的消息格式的数据
            long currentTime = System.currentTimeMillis();
            String resultMess = MessageUtils.getMessage(username, message,currentTime);
            redisTemplate.opsForZSet().add(MESSAGE_KEY,resultMess,currentTime);

            // 挨个遍历已登录用户，然后发送数据
            onlineUsers.forEach((k,v) -> {
                try {
                    v.session.getBasicRemote().sendText(resultMess);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });


        }


    }

    @OnClose
    // 连接关闭时 被调用
    public void onClose(Session session) {
        System.out.println(username + " websocket close!!!");
        onlineUsers.remove(username);
    }

}
